package com.s.core.root.strategy.factor.pic;

import com.google.common.collect.Lists;
import com.s.core.root.data._AllData;
import com.s.core.root.data._PicN;
import com.s.core.root.data._PointN;
import com.s.core.root.strategy.base.Factor;
import com.s.core.root.strategy.base.Feature;
import com.s.core.root.strategy.factor.pic.combination.F_Pic_LastStrong;
import com.s.core.root.strategy.factor.point.F_Point_Max;
import com.s.core.root.strategy.factor.point.F_Point_Strong;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * Pic特征：描述两个或三个point(其中一个是lastPoint)形成的带MaxVol的波动
 */
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class F_Pic_ActivityMax implements Factor, Feature {
    private static final int SKIP_COUNT_IN_GROUP = 1;
    private static final int MAX_INNER = 6;

    public enum TYPE {
        MIDDLE_MAX, //>=3组强，倒数第二组带量
        TAIL_MAX//>=2组强，最后一组带量
    }

    private TYPE type;

    @Override
    public void process(_AllData allData) {
        for (_PicN picN : allData.picNMap.values()) {
            if (picN.containFeature(F_Pic_LastStrong.class)) {
                process(picN.getPointNList1(), picN);
            }
        }
    }

    private void process(List<_PointN> pointNS, _PicN picN) {
        List<List<_PointN>> groupPointNs = getGroup(pointNS);
        if (isMiddleMax(groupPointNs)) {
            picN.addFeature(new F_Pic_ActivityMax(TYPE.MIDDLE_MAX));
        }
        if (isTailMax(groupPointNs)) {
            picN.addFeature(new F_Pic_ActivityMax(TYPE.TAIL_MAX));
        }
    }


    private boolean isMiddleMax(List<List<_PointN>> groupPointNs) {
        return groupPointNs.size() >= 3 &&
                groupPointNs.get(groupPointNs.size() - 2).
                        stream().anyMatch(pointN -> pointN.containFeature(F_Point_Max.class));
    }

    private boolean isTailMax(List<List<_PointN>> groupPointNs) {
        if (groupPointNs.size() >= 2) {
            List<_PointN> last0 = groupPointNs.get(groupPointNs.size() - 1);
            List<_PointN> last1 = groupPointNs.get(groupPointNs.size() - 2);
            if (last0.stream().anyMatch(pointN -> pointN.containFeature(F_Point_Max.class))) {
                _PointN rightPointN = last0.get(0);
                _PointN leftPointN = last1.get(last1.size() - 1);
                return Math.abs(leftPointN.recentIndex - rightPointN.recentIndex) <= MAX_INNER + 1;
            }
        }
        return false;
    }


    private List<List<_PointN>> getGroup(List<_PointN> pointNS) {
        List<List<_PointN>> groupPointNs = Lists.newArrayList();
        int lastRecentX = Integer.MAX_VALUE;
        for (_PointN pointN : pointNS) {
            if (pointN.containFeature(F_Point_Strong.class)) {
                if (Math.abs(pointN.recentIndex - lastRecentX) > SKIP_COUNT_IN_GROUP) {
                    groupPointNs.add(Lists.newArrayList());
                }
                groupPointNs.get(groupPointNs.size() - 1).add(pointN);
                lastRecentX = pointN.recentIndex;
            }
        }
        return groupPointNs;
    }
}
